/**
 * 快速排序算法
快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下，排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较，但这种状况并不常见。事实上，快速排序通常明显比其他Ο(n log n) 算法更快，因为它的内部循环（inner loop）可以在大部分的架构上很有效率地被实现出来。


快速排序使用分治法（Divide and conquer）策略来把一个串行（list）分为两个子串行（sub-lists）。
算法步骤：

1 从数列中挑出一个元素，称为 “基准”（pivot），

2 重新排序数列，所有元素比基准值小的摆放在基准前面，所有元素比基准值大的摆在基准的后面（相同的数可以到任一边）。在这个分区退出之后，该基准就处于数列的中间位置。这个称为分区（partition）操作。

3 递归地（recursive）把小于基准值元素的子数列和大于基准值元素的子数列排序。


递归的最底部情形，是数列的大小是零或一，也就是永远都已经被排序好了。虽然一直递归下去，但是这个算法总会退出，因为在每次的迭代（iteration）中，它至少会把一个元素摆到它最后的位置去。
 */


//这种方案创建了好多数组
(() => {
    let counter = 1;

    function quickSort(ary) {
        var len = ary.length;
        if (len < 3) {
            if (len == 2) {
                var temp = ary[0];
                if (ary[0] > ary[1]) {
                    ary[0] = ary[1];
                    ary[1] = temp;
                }
            }
            return ary;
        }
        var baseIndex = Math.floor(len / 2),//中间的一个做基准
            base = ary[baseIndex];
        var smallerAry = [],
            biggerAry = [];

        // console.warn(`第${counter++}次调用,\t数组长度：${len}，\t基准位置${baseIndex}，\t基准值${base}`) // 这个也会影响速度
        for (var i = len - 1, cur; i > -1; i--) {
            cur = ary[i];
            if (i === baseIndex) {
                continue;
            }
            cur = ary[i];
            cur < base ? (smallerAry[smallerAry.length] = cur) : (biggerAry[biggerAry.length] = cur);
        }
        smallerAry[smallerAry.length] = base;
        // console.log(smallerAry)
        // console.log(biggerAry)
        return quickSort(smallerAry).concat(quickSort(biggerAry));
    }
    const num = 10;
    let arr = generate(num);
    const begin = new Date();

    arr = ConstArr["10000"]
    // console.log(arr);
    console.log(quickSort(arr));
    console.log('用时:\t' + (new Date() - begin));

})();

//http://developer.51cto.com/art/201403/430986.htm
//这种方案，是对原数组的操作，占用内存小
(() => {
    var a = [...ConstArr["10000"]];
    var counter = 0;
    var max = 2000;
    var begin = new Date();
    function quicksort(left, right) {

        var i, j, t, temp;
        if (left > right)
            return;

        temp = a[left]; //temp中存的就是基准数 
        i = left;
        j = right;
        while (i != j) {
            //顺序很重要，要先从右边开始找 
            while (a[j] >= temp && i < j)
                j--;
            //再找右边的 
            while (a[i] <= temp && i < j)
                i++;
            //交换两个数在数组中的位置 
            if (i < j) {
                t = a[i];
                a[i] = a[j];
                a[j] = t;
            }
        }
        if (counter++ > 2000) {//调试用，避免死循环
            // return;
        }
        //最终将基准数归位 
        a[left] = a[i];
        a[i] = temp;

        quicksort(left, i - 1);//继续处理左边的，这里是一个递归的过程 
        quicksort(i + 1, right);//继续处理右边的 ，这里是一个递归的过程 

    }
    quicksort(0, a.length - 1);
    console.log('用时:\t' + (new Date() - begin));
    console.log(a)
})();